﻿#pragma once
#include "OpenGL项目主标头.h"
#include "OpenGL渲染器类标头.h"
//#include "header/OpenGL渲染器类标头.h"
// C/C++ 标准库学习网站：https://legacy.cplusplus.com
// C/C++ 参考学习网站：https://zh.cppreference.com/w/cpp
// C/C++ 微软(Visual Studio)中文学习网站：https://learn.microsoft.com/zh-cn/cpp/cpp/?view=msvc-170
// OpenGl 学习网站：https://www.khronos.org/opengl/wiki
// OpenGl 的 GLFW 学习网站：https://www.glfw.org/docs/latest/glfw3_8h.html#ac06b663d79c8fcf04669cc8fcc0b7670
// OpenGl 的 GLEW 学习网站：https://docs.gl/

static std::string get_now_time() {
	time_t now = time(0);
	struct tm t_struct;
	char buf[80];
	localtime_s(&t_struct, &now);
	strftime(buf, sizeof(buf), "%Y-%m-%d %X", &t_struct);  // 将时间格式化为字符串
	//cout << "now time: " << buf << endl;
	return buf;
}

void gl_clean_error() {
	while (glGetError() != GL_NO_ERROR);  // 清除 OpenGL 错误
}

bool gl_check_error(const char* file, const char* function, int line) {
	const char* filename = "Log/glGetErrorLog.txt";
	//cout << "now time: " << get_now_time() << endl;
	GLenum error = glGetError();
	std::string error_string;
	switch (error) {    // 输出 OpenGL 错误一些常见的信息，只输出一次
	case GL_INVALID_ENUM:
		error_string = "gl_invalid_enum";
		break;
	case GL_INVALID_VALUE:
		error_string = "gl_invalid_value";
		break;
	case GL_INVALID_OPERATION:
		error_string = "gl_invalid_operation";
		break;
	case GL_STACK_OVERFLOW:
		error_string = "gl_stack_overflow";
		break;
	case GL_STACK_UNDERFLOW:
		error_string = "gl_stack_underflow";
		break;
	case GL_OUT_OF_MEMORY:
		error_string = "gl_out_of_memory";
		break;
	case GL_INVALID_FRAMEBUFFER_OPERATION:
		error_string = "gl_invalid_framebuffer_operation";
		break;
	default:
		error_string = "Unknown";
		break;
	}
	if (/*GL_NO_ERROR == */!error)
		return true;
	else {
		cout << get_now_time() << " [OpenGL Error]: (" << error << "): "
			<< error_string << "        " << file << " in function " << function << " at line "
			<< line << endl;
		return false;
	}
	//std::fstream log_file(filename, std::ios::out | std::ios::app);
	//if (log_file.is_open()) {  // 打开日志文件错误
	//	log_file << get_now_time() << " (" << error << ")" << " written in " << filename << "failed." << std::endl;
	//}
	///*std::string error_info = "OpenGL Error: (" + error_string + "); error_code: " + std::to_string(error) + "; occurred at " + get_now_time();
	//log_file.write(error_info.c_str(), error_string.size());*/
	//log_file.close();
}

// 渲染器类 Renderer 的实现
void Renderer::clear() const {
	gl_call(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); // 清除颜色缓冲区和深度缓冲区
}

void Renderer::draw(const VertexArray& va, const IndexBuffer& ib, const Shader& sd) {
	va.bind();		  // 绑定顶点数组
	ib.bind();		  // 绑定索引缓冲区
	sd.use_program(); // 绑定着色器 Release 模式不写这行
	// 实际发布模式下可能不需要绑定、解绑等操作（因为其会消耗一部分资源）
	gl_call(glDrawElements(GL_TRIANGLES, ib.get_count(), GL_UNSIGNED_INT, nullptr)); // 绘制索引数组
}